<template>
	<el-select
		ref="select"
		v-model="currentValue"
		:disabled="disabled"
		:filterable="filterable"
		:multiple="multiple"
		:clearable="clearable"
		:size="size"
		:placeholder="placeholder"
		:multiple-limit="multipleLimit"
		:collapse-tags="collapseTags"
		:allow-create="allowCreate"
		:filter-method="filterMethodHandler"
		:remote="remote"
		:remote-method="remoteMethod"
		:popper-append-to-body="popperAppendToBody"
		:popper-class="poperClass"
		:loading="loading"
		:class="{'isBlock': isBlock}"
		@change="onChange"
		@visible-change="onVisibleChange"
		@remove-tag="removeTag"
		@clear="onClear"
		@blur="onBlur"
		@focus="onFocus"
		@keyup.enter.native="onSelectEnter"
	>
		<slot :optionlist="currentOptionList" :optionProp="optionProp">
			<el-option
				v-for="item in currentOptionList"
				:key="item[optionProp.key]"
				:label="item[optionProp.label]"
				:value="item[optionProp.value]"
				:disabled="item[optionProp.disabled]"
			>
			</el-option>
		</slot>
	</el-select>
</template>
<script>
/**
 * select by shang 2020/11/5
 * @desc select 选择框
 * @param {value}  [any] - 输入框值
 * @param {disabled}  [Boolean] - 是否禁用
 * @param {filterable}  [Boolean] - 开启筛选 默认开启
 * @param {multiple}  [Boolean] - 多选
 * @param {clearable}  [Boolean] - 清除功能
 * @param {size}  [String] - 尺寸
 * @param {placeholder}  [String] - 默认提示
 * @param {multipleLimit}  [Number] - 多选上限
 * @param {collapseTags}  [Number] - 多选上限
 * @param {allowCreate}  [Boolean] - 用户新增选项功能
 * @param {filterMethod}  [Function] - 自定义筛选
 * @param {filterKeys}  [Array] - 筛选keys
 * @param {optionlist}  [Array] - 选项集合
 * @param {optionProp}  [Object] - 选项字段
 * @param {popperAppendToBody}  [Boolean] - 是否将弹出框插入至 body 元素
 * @param {poperClass}  [String] - 下拉框类名
 *
 * @event {change} 选项发生变化触发
 * @event {blur} 输入框失焦时触发
 * @event {focus} 输入框聚焦时触发
 */
const SEARCH_PROPS = ['name', 'code', 'sign', 'completeSign']
export default {
	name: 'w-select',
	props: {
		value: null,
		disabled: Boolean,
		filterable: {
			type: Boolean,
			default: true
		},
		multiple: Boolean,
		clearable: Boolean,
		size: {
			type: String,
			default: 'mini'
		},
		placeholder: {
			type: String,
			default: '请选择'
		},
		multipleLimit: {
			type: Number,
			default: 0
		},
		collapseTags: Boolean,
		allowCreate: {
			type: Boolean,
			default: false
		},
		remote: Boolean,
		remoteMethod: Function,
		filterMethod: Function,
		filterKeys: {
			type: Array,
			default: () => {
				return SEARCH_PROPS
			}
		},
		optionlist: {
			type: Array,
			default: () => {
				return []
			}
		},
		optionProp: {
			type: Object,
			default: () => {
				return {
					key: 'id',
					label: 'name',
					value: 'id',
					disabled: 'disabled'
				}
			}
		},
		popperAppendToBody: {
			type: Boolean,
			default: true
		},
		poperClass: String,
		loading: {
			type: Boolean
		},
		isBlock: {
			type: Boolean,
			default: false
		}
	},
	data () {
		return {
			currentValue: '',
			searchKey: ''
		}
	},
	computed: {
		currentOptionList () {
			return this.optionlist.filter(item => {
				return this.$fxUtils.fuzzyQueryObj(item, this.searchKey, SEARCH_PROPS)
			})
		}
	},
	watch: {
		value: {
			immediate: true,
			handler (val, oldVal) {
				this.currentValue = val
			}
		},
		currentValue (val) {
			this.$emit('input', val)
		}
	},
	methods: {
		onChange (item) {
			this.$emit('change', item)
		},
		onVisibleChange (visible) {
			setTimeout(() => {
				this.searchKey = ''
			}, 500)
			const selectIndex = this.optionlist.findIndex(item => {
				return item[this.optionProp.key] === this.value
			})
			this.$refs.select.hoverIndex = ~selectIndex ? selectIndex : 0
			this.$refs.select.query = ''
			this.$emit('visible-change', visible)
		},
		removeTag (item) {
			this.$emit('remove-tag', item)
		},
		onClear () {
			this.$emit('clear')
		},
		onBlur (e) {
			// 当是可以新增条目的时候 失去焦点 给input赋值
			if (this.allowCreate && this.searchKey) {
				this.currentValue = this.searchKey
				this.$emit('blur', e, this.currentValue)
			} else {
				this.$emit('blur', e)
			}
		},
		onFocus (e) {
			this.$emit('focus', e)
		},
		filterMethodHandler (searchKey) {
			this.searchKey = searchKey
			if (typeof this.filterMethod === 'function') {
				this.filterMethod(searchKey)
			}
		},
		focus () {
			this.$refs.select.focus()
		},
		blur () {
			this.$refs.select.blur()
		},
		onSelectEnter (event) {
			const visible = this.$refs.select.visible
			if (!visible) {
				this.$emit('on-select-enter', event)
			}
		}
	}
}
</script>
<style lang="stylus" scoped>
	.isBlock {
		display: block
	}
</style>
